package com.ruoyi.common.utils.bean;

import com.ruoyi.common.utils.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;

/**
 * @Classname InvokeUtils
 * @Author: sunluquan
 * @Date: 2022/6/13 14:59
 * @Description TODO
 * 调用方法相关工具类
 */
public class InvokeUtils {


    /**
     * 校验是否为为class包名
     *
     * @param invokeTarget 名称
     * @return true是 false否
     */
    public static boolean isValidClassName(String invokeTarget){
        return StringUtils.indexOf(invokeTarget,'.')>1;
    }

    /**
     * 获取bean名称
     *
     * @param invokeTarget 目标字符串
     * @return bean名称
     */
    public static String getBeanName(String invokeTarget){
        return StringUtils.substringBeforeLast(StringUtils.substringBefore(invokeTarget,"("),".");
    }

    /**
     * 获取bean方法
     *
     * @param invokeTarget 目标字符串
     * @return method方法
     */
    public static String getMethodName(String invokeTarget){

        String className = StringUtils.substringBeforeLast(invokeTarget,"(");

        return StringUtils.substringAfterLast(className,".");

    }

    /**
     * 调用任务方法
     *
     * @param bean 目标对象
     * @param methodName 方法名称
     * @param methodParams 方法参数
     */
    public static  void invokeMethod(Object bean,String methodName,List<Object[]> methodParams)
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        Method method = bean.getClass().getDeclaredMethod(methodName, getMethodParamsType(methodParams));

        method.invoke(bean,getMethodParams(methodParams));
    }

    /**
     * 获取method方法参数相关列表
     *
     * @param invokeTarget 目标字符串
     * @return method方法相关参数列表
     */
    public static List<Object[]> getMethodParams(String invokeTarget)
    {
        String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")");
        if (StringUtils.isEmpty(methodStr))
        {
            return null;
        }
        String[] methodParams = methodStr.split(",(?=([^\"']*[\"'][^\"']*[\"'])*[^\"']*$)");
        List<Object[]> classs = new LinkedList<>();
        for (int i = 0; i < methodParams.length; i++)
        {
            String str = StringUtils.trimToEmpty(methodParams[i]);
            // String字符串类型，以'或"开头
            if (StringUtils.startsWithAny(str, "'", "\""))
            {
                classs.add(new Object[] { StringUtils.substring(str, 1, str.length() - 1), String.class });
            }
            // boolean布尔类型，等于true或者false
            else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str))
            {
                classs.add(new Object[] { Boolean.valueOf(str), Boolean.class });
            }
            // long长整形，以L结尾
            else if (StringUtils.endsWith(str, "L"))
            {
                classs.add(new Object[] { Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class });
            }
            // double浮点类型，以D结尾
            else if (StringUtils.endsWith(str, "D"))
            {
                classs.add(new Object[] { Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class });
            }
            // 其他类型归类为整形
            else
            {
                classs.add(new Object[] { Integer.valueOf(str), Integer.class });
            }
        }
        return classs;
    }

    /**
     * 获取参数类型
     *
     * @param methodParams 参数相关列表
     * @return 参数类型列表
     */
    public static Class<?> [] getMethodParamsType(List<Object[]> methodParams){

        Class<?> [] classTypes = new Class[methodParams.size()];

        int index = 0;

        for(Object[] objects : methodParams){
            classTypes[index++] = (Class<?>)objects[1];
        }

        return classTypes;
    }

    /**
     * 获取参数值
     *
     * @param methodParams 参数相关列表
     * @return 参数值列表
     */
    public static Object [] getMethodParams(List<Object[]> methodParams){
        Object [] params = new Object[methodParams.size()];

        int index = 0;

        for(Object[] objects : methodParams){
            params[index++] = (Object)objects[0];
        }

        return params;
    }

}
